# 3. lottie_players.py
import os
import numpy as np
import rlottie_python as rlottie
from PIL import Image

# ========== 拆分LottiePlayer为两个类，一个是静态连续渲染使用，一个嘴型动态播放和控制倒播526修改 ==========
# LottiePlayer 静态渲染，是连续帧的渲染播放
class LottiePlayerStatic:
    def __init__(self, json_path):
        self.animation = rlottie.LottieAnimation.from_file(os.path.abspath(json_path))
        self.total_frames = self.animation.lottie_animation_get_totalframe()
        self.width, self.height = self.animation.lottie_animation_get_size()
        self.start_frame, self.end_frame = 0, self.total_frames - 1
        self.current_frame = self.start_frame

    def set_play_segment(self, start, end):
        self.start_frame = start
        self.end_frame = end
        self.current_frame = self.start_frame
        print(f"[LottiePlayerStatic] 设置播放段：{start}-{end}")

    def render_next_frame(self):
        frame_bytes = self.animation.lottie_animation_render(
            frame_num=int(self.current_frame), width=self.width, height=self.height)
        rgba_frame = np.frombuffer(frame_bytes, dtype=np.uint8).reshape((self.height, self.width, 4))
        rgba_frame = rgba_frame[..., [2, 1, 0, 3]]

        if self.current_frame < self.end_frame:
            self.current_frame += 1

        return Image.fromarray(rgba_frame, mode="RGBA")

# 唇形同步动态渲染类，跳帧的正播
class LottiePlayerDynamicForward:
    def __init__(self, json_path):
        self.animation = rlottie.LottieAnimation.from_file(os.path.abspath(json_path))
        self.total_frames = self.animation.lottie_animation_get_totalframe()
        self.width, self.height = self.animation.lottie_animation_get_size()
        self.play_frames = []
        self.current_index = 0
        self.current_frame = 0

    def set_play_sequence(self, frame_list):
        self.play_frames = frame_list
        self.current_index = 0
        self.current_frame = frame_list[0] if frame_list else 0
        print(f"[LottiePlayerDynamicForward] 设置播放帧序列：{frame_list}")

    def render_next_frame(self):
        if not self.play_frames:
            print("[LottiePlayerDynamicForward] 播放序列为空，返回默认帧")
            frame_to_render = 0
        elif self.current_index < len(self.play_frames):
            frame_to_render = self.play_frames[self.current_index]
            self.current_frame = frame_to_render
            print(f"[F1渲染跳帧] index={self.current_index}, frame={self.current_frame}")
            self.current_index += 1
        else:
            frame_to_render = self.play_frames[-1]
            self.current_frame = frame_to_render
            print(f"[F2维持最后帧] index={self.current_index}, frame={self.current_frame}")

        frame_bytes = self.animation.lottie_animation_render(
            frame_num=int(frame_to_render), width=self.width, height=self.height)
        rgba_frame = np.frombuffer(frame_bytes, dtype=np.uint8).reshape((self.height, self.width, 4))
        rgba_frame = rgba_frame[..., [2, 1, 0, 3]]  # BGRA -> RGBA
        return Image.fromarray(rgba_frame, mode="RGBA")

# 唇形同步动态渲染类，跳帧的倒播
class LottiePlayerDynamicReverse:
    def __init__(self, json_path):
        self.animation = rlottie.LottieAnimation.from_file(os.path.abspath(json_path))
        self.total_frames = self.animation.lottie_animation_get_totalframe()
        self.width, self.height = self.animation.lottie_animation_get_size()
        self.play_frames = []
        self.total_count = 0
        self.current_index = 0
        self.current_frame = 0

    def set_play_sequence(self, frame_list):
        if frame_list and frame_list[0] > frame_list[-1]:
            #print("[⚠️警告] 倒序帧输入 detected，已自动 reverse")
            frame_list = list(reversed(frame_list))
        self.play_frames = frame_list
        self.total_count = len(frame_list)
        self.current_index = 0
        self.current_frame = frame_list[-1] if frame_list else 0
        print(f"[LottiePlayerDynamicReverse] 设置播放帧序列：{frame_list}")

    def render_next_frame(self):
        if not self.play_frames:
            print("[LottiePlayerDynamicReverse] 播放序列为空，返回默认帧")
            frame_to_render = 0
        elif self.current_index < self.total_count:
            # 倒序访问：从末尾到开头
            frame_to_render = self.play_frames[self.total_count - 1 - self.current_index]
            self.current_frame = frame_to_render
            print(f"[R1渲染跳帧] index={self.current_index}, frame={self.current_frame}")
            self.current_index += 1
        else:
            frame_to_render = self.play_frames[0]
            self.current_frame = frame_to_render
            print(f"[R2维持第一帧] index={self.current_index}, frame={self.current_frame}")

        frame_bytes = self.animation.lottie_animation_render(
            frame_num=int(frame_to_render), width=self.width, height=self.height)
        rgba_frame = np.frombuffer(frame_bytes, dtype=np.uint8).reshape((self.height, self.width, 4))
        rgba_frame = rgba_frame[..., [2, 1, 0, 3]]  # BGRA -> RGBA
        return Image.fromarray(rgba_frame, mode="RGBA")